#pragma once
#include<iostream>
#include<thread>
#include<queue>
#include<mutex>
#include<vector>
#include<atomic>
#include<chrono>
#include<condition_variable>
//#define THREADNUMBER 10

class TaskContext{
public:
    virtual void Run() = 0;
    virtual ~TaskContext(){

    }
};


class Threatpool{
public:
    Threatpool(int threadnNumber){
        isExit.store(0);
        for (int i = 0; i < threadnNumber; i++)
        {
            threadpool.push_back(std::thread(&Threatpool::threadIn,this));
        }

    }
    void threadIn(){
        while (!isExit)
        {
            std::unique_lock<std::mutex> l(taskmutex);
            if(Task.empty()){
                taskCondition.wait(l,[this](){
                    return this->Exit() || !this->TaskEmpty();
                });
            }
            if(Exit()){
                break;
            }
            TaskContext* task=Task.front();
            Task.pop();
            l.unlock();
            task->Run();
            //防止运行过快，线程一直抢占锁
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }
    }
    bool TaskEmpty(){
        return Task.empty();
    }
    bool Exit(){
        if(isExit){
            return true;
        }
        return false;
    }
    void pushTask(TaskContext* task){
        //taskmutex.lock();
        std::unique_lock<std::mutex> l(taskmutex);
        Task.push(task);
        l.unlock();
        taskCondition.notify_all();
        //taskCondition.notify_one();
        //taskmutex.unlock();
    }
    void Close(){
        isExit.fetch_add(1);
        taskCondition.notify_all();
        for (int i = 0; i < threadpool.size(); i++)
        {
            threadpool[i].join();
        }
    }
protected:
    std::vector<std::thread> threadpool;
    std::mutex taskmutex;
    std::queue<TaskContext*> Task;
    std::atomic<int> isExit;
    std::condition_variable taskCondition;
};